#pragma once
#include <iostream>
#include <string>
#include <stdexcept>
#include <memory>
#include <optional>

// Use string.c_str()
template <typename... Args>
std::string format(const std::string& format, Args... args)
{
    // Extra space for '\0'
    int size_s = std::snprintf(nullptr, 0, format.c_str(), args...) + 1;

    if (size_s <= 0)
        throw std::runtime_error("Error during formatting.");

    size_t size = static_cast<size_t>(size_s);
    auto buf = std::make_unique<char[]>(size);
    std::snprintf(buf.get(), size, format.c_str(), args...);

    // We don't want the '\0' inside
    return std::string(buf.get(), buf.get() + size - 1);
}

void print(const char* s);

// This function provide typesafety than printf
template <typename T, typename... Args>
void print(const char* s, const T& value, const Args &...args)
{
	while (*s)
	{
		if (*s == '%' && *++s != '%')
		{
			std::cout << value;
			return print(++s, args...);
		}
		std::cout << *s++;
	}
	throw std::runtime_error("extra arguments provided to printf");
}

std::optional<std::string> readfile(const std::string& file_path);